/*
 * 图片识别，通过摄像头，上传图片
 * Created by RisingSun. 
 * User: MarkSpace 
 * Date: 20220419
 * Time: 11:05 
*/
layui.extend({
  setter: 'config' //配置模块
  ,tesseract: 'lib/extend/tesseract' //识别核心库
}).define(['setter','tesseract'],function(exports){ //提示：模块也可以依赖其它模块，

var setter = layui.setter;
var $ = layui.jquery;
const { createWorker } = Tesseract;

var picturetota = {
    render:function($this, options){
        var divID;
        var that=this,language,languagepath,type,imgUrl,debug,audioStatus;

        this.divID = $this;
        this.language =options.language ? options.language : 'chisim';
        this.languagepath = options.languagepath ? options.languagepath : '/static/lay/lib/lang-data';
        this.type = options.type ? options.type : 'text';  // 识别操作，text图片转文字，Audio转声音
        this.sourcetype = options.sourcetype ? options.sourcetype : 'pic';  // 输入类型，pic图片，camera摄像头
        this.imgUrl = options.imgurl ? options.imgurl : '/static/lay/lib/models/ceshi2.png';
        this.mediaSize  = options.mediasize ? options.mediasize : { width: 640, height:360 };
        this.debug = options.debug ? options.debug : false;
        this.audioStatus = options.audio ? options.audio : true;
        this.audioConfig = options.audioconfig ? options.audioconfig :{ lang: 'zh', volume:2 ,rate:0.5, pitch:1 };

        that.resize();

        // this.video = document.querySelector('#video');
        // this.photograph = document.querySelector('#photograph');
        // this.pictureagain = document.querySelector('#pictureagain');
        this.startcheck = document.querySelector('#startcheck');
        
        $(document).on('click','input[name="sourcetype"]', function(e){
            if($(this).val()=='camera'){
                this.sourcetype='camera'; 
                $('#picbox').html='';
                content ='<img id="img" style="width:'+picturetota.mediaSize.width+'px; height:'+picturetota.mediaSize.height+'px;">';
                content +='<VIDEO id="video" autoplay muted width='+picturetota.mediaSize.width+' height='+picturetota.mediaSize.height+' style="z-index:10;position: absolute;"></VIDEO>';
                content +='<canvas id="canvasImg" style="z-index:99; position: absolute;"></canvas>';
                $('#picbox').html(content);
                $('#getbtn').html='';
                content ='<button id="photograph">拍照</button>';
                content +='<button id="pictureagain">重新拍照</button>';
                $('#getbtn').html(content);
                that.drawViewFinder();
                that.startVideo();

            }else if ($(this).val()=='pic'){
                this.sourcetype='pic'; 
                $('#picbox').html='';
                video.srcObject.getTracks().forEach(function(value){
                    value.stop();
                })
                content ='<img id="img">';
                $('#picbox').html(content);
                $('#getbtn').html='';
                content +='<label>上传图片：</label>';
                content +='<input type="file" onchange="layui.picturetota.preview(this)" />';
                $('#getbtn').html(content);
            }
            
        })


        if(this.sourcetype=='camera' || $("input[name='sourcetype']:checked").val()=='camera'){
            that.drawViewFinder();
            that.startVideo();
        }

        that.bindEvents();

    },
    /*设置相关容器*/
    resize:function() {
        var content='';
        //动态创建css
        var style = document.createElement('style');
        style.type = 'text/css';
        style.rel = 'stylesheet';
        var code ='button{margin: 0 5px;display: inline-block;vertical-align: middle;height: 38px;line-height: 38px;border: 1px solid transparent;padding: 0 18px;background-color: #1e9fff;color: #fff;white-space: nowrap;text-align: center;font-size: 14px;border-radius: 2px;cursor: pointer;}';
            code +='button:hover {background-color: #4CAF50; color: white;}';
            code +='input[type="radio"]{width: 18px; height: 18px; padding:2px; background-color: #fff; border: 1px solid #c9c9c9; border-radius: 2px; color: #fff; text-align: center; line-height: 15px; -webkit-appearance: none; appearance: none; outline: none; margin:0 10px 0 5px; cursor: pointer;}';
            code +='input[type="radio"]:hover{ border: 1px solid #43adea;}';
            code +='input[type="radio"]:checked{color: #fff; background-color: #43adea; border: 1px solid #43adea;}';
            code +='input[type="radio"]:after{content: "√";}';
            code += this.divID+'{width:100%; height:100%;position: absolute; left:50%;right: 50%;transform: translateX(-50%);}';
            code +='#leftdiv{font-size:16px;float:left; width:calc(50% - 40px); padding:10px 20px;position: absolute;top: 0;left: 0;}';
            code +='#rightdiv{font-size:16px;float:right; width:calc(50% - 40px); padding:10px 0px;position: absolute;top: 0;right: 0;}';
            code +='.title{width:100%;height:45px; line-height:45px;font-size:16px;font-weight:bold;position: absolute;}';
            code +='#video{position: absolute; }';
            code +='#load {left: 50%; height: 45px; line-height: 45px;position: absolute; display:none;}';
            code +='#text{ padding:10px;}'
            
            code +='select{margin: 0 5px;display: inline-block;vertical-align: middle;height: 38px;line-height: 38px;border: 1px solid #1e9fff ;padding: 0 18px;white-space: nowrap;text-align: center;font-size: 14px;border-radius: 2px;cursor: pointer;}';
        
        try{
        style .appendChild(document.createTextNode(code));//for Chrome Firefox Opera Safari
        }catch(ex){
        style.styleSheet.cssText = code;//for IE
        }
        var head = document.getElementsByTagName('head')[0];//for IE
        head.appendChild(style);

        const wraper = document.querySelector(this.divID);

        const leftdiv=document.createElement("div");
        leftdiv.setAttribute("id", 'leftdiv');
        content ='<div class="title">图片识别文字';
        content +='<label for="withFaceLandmarks" style="margin-left:50px;">拍照</label>';
        content +='<input type="radio" name="sourcetype" value="camera"';
        if(this.sourcetype=='camera'){
           content +='checked="checked"'; 
        }
        content +='/>';
        content +='<label for="hideBoundingBoxes" >图片</label>';
        content +='<input type="radio" name="sourcetype" value="pic"';
        if(this.sourcetype=='pic'){
           content +='checked="checked"'; 
        }
        content +='/>';
        content +='</div>';

        if(this.sourcetype=='camera'){
        content +='<div id="picbox" style="position: absolute; top:55px; text-align:center; left:50%;right: 50%;transform: translateX(-50%);display: flex;align-items: center;justify-content: center;">';
        content +='<img id="img" style="width:'+this.mediaSize.width+'px; height:'+this.mediaSize.height+'px;">'
        content +='<VIDEO id="video" autoplay muted width='+this.mediaSize.width+' height='+this.mediaSize.height+' style="z-index:10;position: absolute;"></VIDEO>';
        content +='<canvas id="canvasImg" style="z-index:99; position: absolute;"></canvas>';
        content +='</div>';
        }
        if(this.sourcetype=='pic'){
        content +='<div id="picbox" style="position: absolute; top:55px; text-align:center; left:50%;right: 50%;transform: translateX(-50%);display: flex;align-items: center;justify-content: center;">';
        content +='<img id="img">';
        content +='</div>';
        }

        content +='<div style="width:100%;height:45px;position: absolute;top:'+(this.mediaSize.height+75)+'px">';
        if(this.sourcetype=='pic'){
        content +='<div id="getbtn" style="float:left">';
        content +='<label>上传图片：</label>';
        content +='<input type="file" onchange="layui.picturetota.preview(this)" />';
        content +='</div>';
        }
        if(this.sourcetype=='camera'){
        content +='<div id="getbtn" style="float:left">';
        content +='<button id="photograph">拍照</button>';
        content +='<button id="pictureagain">重新拍照</button>';
        content +='</div>';
        }
        content +='<div style="float:left">'
        content +='<button id="startcheck">识别</button>';
        if(this.audioStatus){
        content +='<button id="startAudio" style="display:none;">播放语音</button>';
        content +='<button id="stopAudio" style="display:none;">停止播放</button>';
        }
        content +='</div>'
        content +='</div>';

        leftdiv.innerHTML=content;
        wraper.appendChild(leftdiv);


        const rightdiv=document.createElement("div");
        rightdiv.setAttribute("id", 'rightdiv');
        content ='<div class="title">结果显示</div><div id="load">识别中...</div>';
        content +='<div id="text" style="position: absolute;top:55px; border:1px solid #e2e2e2;width:'+this.mediaSize.width+'px; height:'+this.mediaSize.height+'px;">';
        content +='</div>';
        rightdiv.innerHTML=content;
        wraper.appendChild(rightdiv);

    },
    /** @name 绘制取景框 */
    getdebug(m) { 
        if(this.debug){   
            console.log(m)
        }
    },

    /** @name 绘制取景框 */
    drawViewFinder() {
    canvasImg=document.querySelector('#canvasImg');  
    const context = canvasImg.getContext("2d");
    if (!context) return;
    canvasImg.setAttribute('width', this.mediaSize.width - 80);
    canvasImg.setAttribute('height', this.mediaSize.height - 80);
      // topleft
      context.beginPath();//开启当前的绘制路径
      context.moveTo(0, 0);
      context.lineTo(canvasImg.width,0);
      context.moveTo(0,0);
      context.lineTo(0,canvasImg.height);
      context.lineWidth = 4;
      context.strokeStyle = "#1e9fff";
      context.stroke();//沿着坐标点的路径顺序绘制直线  
      context.closePath();   //关闭当前的绘制路径

      // bottomright
      context.beginPath();//开启当前的绘制路径
      context.moveTo(canvasImg.width,canvasImg.height);
      context.lineTo(canvasImg.width,0);
      context.moveTo(canvasImg.width,canvasImg.height);
      context.lineTo(0,canvasImg.height);
      context.lineWidth = 4;
      context.strokeStyle = "#1e9fff"; 
      context.stroke();//沿着坐标点的路径顺序绘制直线
      context.closePath();   //关闭当前的绘制路径

    },
    /** @name 采集视频流 */
    startVideo:function() {
        if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator
            .mozGetUserMedia) {
            //调用用户媒体设备, 访问摄像头
            this.getUserMedia({
                video: {
                    width: this.mediaSize.width,
                    height: this.mediaSize.height
                },
                audio: false  //不适用音频
            }, this.success, this.mediaErrorCallback);
        } else {
            layer.alert('不支持访问用户媒体');
        }
    },
    /** @name 获取视频流 */
    getUserMedia:function(constraints, success, error) {
            if (navigator.mediaDevices.getUserMedia) {
                //最新的标准API
                navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
            } else if (navigator.webkitGetUserMedia) {
                //webkit核心浏览器
                navigator.webkitGetUserMedia(constraints, success, error)
            } else if (navigator.mozGetUserMedia) {
                //firfox浏览器
                navigator.mozGetUserMedia(constraints, success, error);
            } else if (navigator.getUserMedia) {
                //旧版API
                navigator.getUserMedia(constraints, success, error);
            }
        },
    /** @name 成功 */
    success:function(stream) {
            //兼容webkit核心浏览器
            let CompatibleURL = window.URL || window.webkitURL;
            //播放
            video.srcObject = stream;
            video.play();
    },
    /*获取媒体流错误处理*/
    mediaErrorCallback:function(error) {
        const errorMap = {
           'NotSupportedError':'浏览器不支持http访问用户媒体',
           'NotAllowedError': '摄像头已被禁用，请在当前浏览器设置中开启后重试',
           'AbortError': '硬件问题，导致无法访问摄像头',
           'NotFoundError': '未检测到可用摄像头',
           'NotReadableError': '操作系统上某个硬件、浏览器或者网页层面发生错误，导致无法访问摄像头',
           'OverConstrainedError': '未检测到可用摄像头',
           'SecurityError': '摄像头已被禁用，请在系统设置或者浏览器设置中开启后重试',
           'TypeError': '类型错误，未检测到可用摄像头'
          };
        if (errorMap[error.name]) {
          layer.alert(errorMap[error.name]);
        }
    },

    /*人脸识别弹框的相关事件绑定*/
    bindEvents() {
            // "拍照" 按钮
        $(document).on('click','#photograph', function(e){
            picturetota.getpicture(video);
            video.pause();
        });
            // "重新拍照" 按钮
        $(document).on('click','#pictureagain', function(e){
            video.play();
        });

            // "识别" 按钮
        $(document).on('click','#startcheck', function(e){
            picturetota.run();
        });

            // "播放" 按钮
        $(document).on('click','#startAudio', function(e){
            picturetota.startAudio();
            document.querySelector('#startAudio').style.display="none";
            document.querySelector('#stopAudio').style.display="";
        });
            // "停止" 按钮
        $(document).on('click','#stopAudio', function(e){
            picturetota.stopAudio();
            document.querySelector('#startAudio').style.display="";
            document.querySelector('#stopAudio').style.display="none";
        });
    },

    /** @name 精确验证人脸 */
    async getpicture(videoEL) {
        var canvas = document.createElement('canvas');
        canvas.height = videoEL.height
        canvas.width = videoEL.width
        canvas.getContext('2d').drawImage(video,0, 0, videoEL.width, videoEL.height);
        document.getElementById('img').src = canvas.toDataURL("image/png");
    },

    /** @name 初始化文字框 */
    init(text) {
      var textArray = text.split(/[,，\s\n]/), sArray = '';
                textArray = textArray.filter((s)=>{
                    if (s) {
                        s = '<div class="poem">' + s + '</div>';
                        sArray += s;
                        return s;
                    }   
                })
                str = textArray.join('\n\n');
                document.getElementById('text').innerHTML = sArray;
    },
    /** @name 检测图片转为文字 */
    async run() {
      
      let base64 = document.getElementById('img').src;

      const worker = createWorker({
                workerPath: '/static/lay/lib/extend/worker.js',
                langPath: this.languagepath,
                corePath: '/static/lay/lib/extend/tesseract-core.wasm.js',
                logger: m => this.getdebug(m),
        });
        
        var str = '';

        (async () => {
                document.querySelector('#load').style.display="block";
                document.getElementById('startcheck').innerText = '识别中···'
                await worker.load();
                await worker.loadLanguage(this.language);
                await worker.initialize(this.language);
                const { data: { text } } = await worker.recognize(base64);
                picturetota.init(text);
                await worker.terminate();
                document.querySelector('#load').style.display="none";
                document.getElementById('startcheck').innerText = '识别';
                document.querySelector('#startAudio').style.display="";
            })();
    },

    /** @name 上传图片 */
    preview(file,width=640,height=480){
        var img = document.getElementById('img');
        if(file.files && file.files[0]) {
               var reader = new FileReader();
                reader.onload = function(evt) {
                img.src = evt.target.result;
                img.setAttribute("style", 'width:'+width+'px; height:'+height+'px;');
               } 
               reader.readAsDataURL(file.files[0]);  
          } else {
                 layer.alert(file.value);
          }
    },
    /** @name 播放音频 */
    startAudio() {
        document.getElementsByClassName('poem')[document.getElementsByClassName('poem').length - 1].style.color = '#000000';
        sum=document.getElementsByClassName('poem').length;
        let lines = 0;
            if(str) {
                var msg = new SpeechSynthesisUtterance(str);
                msg.lang = this.audioConfig.lang; //汉语
                msg.volume = this.audioConfig.volume;   //音量
                msg.rate = this.audioConfig.rate;  //语速
                msg.pitch = this.audioConfig.pitch;  // 表示说话的音高，数值，范围从0(最小)到2(最大)。默认值为1
                window.speechSynthesis.speak(msg);
                msg.onboundary = function(event) {  //播放监听
                if(event.name == 'sentence') {
                    document.getElementsByClassName('poem')[lines].style.color = '#FF0000';
                    if(lines > 0){document.getElementsByClassName('poem')[lines - 1].style.color = '#000000';}
                    lines ++;
                }
                if(lines==sum){
                   document.querySelector('#startAudio').style.display="";
                   document.querySelector('#stopAudio').style.display="none"; 
                }
            }
            
        }
    },
    /** @name 播放音频 */
    stopAudio() {
        window.speechSynthesis.cancel();
    }
    
}

exports('picturetota', picturetota);
});

